www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using tango or other static lib in static lib

reply Voitech <woipoi gmail.com> writes:
At beginning I want to say that I'm Java devloper so most of 
linking, joining, dependent classes, libs could be solve with 
simple 3 click in eclipse so please be patient with me :).
I'm using Mono-D under Ubuntu 14.04 to create my project it would 
be a library for further development process, but I'm a guy who 
don't want to invite wheel again and again, so i wanted to use 
Tango-D2 (for now HashMap implemenetation). From what i red you 
cant import one static library with another but somehow import o. 
files, or just copy sources .d to proper folder and use them as 
yours (with proper license of course). Tango-D2 by itself 
compiles nicely with bob and produces many .o files. How to use 
them though ?
If using sources by just copping them into one folder, creating 
Mono-D project, dmd complains about many, many errors, mostly 
import errors (in tango.sys.win32). I fixed them adding version 
to each of included files and adding some imports first:
module tango.sys.win32....
version(Windows){
...
...
}

But i think I'm doing something wrong, if Tango-D2 compiles with 
bob it should also by creating project in Mono-D (or this is 
linking problem ?). In Mono-D there is also possibility in 
Project-> Options-> Build-> Compiling to add Libraries (there is 
a tick Link static libraries from nested dependencies) how to use 
this ? Or rather how should i obtain what i want ?
Mar 12 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 12 March 2016 at 22:34:19 UTC, Voitech wrote:
 At beginning I want to say that I'm Java devloper so most of 
 linking, joining, dependent classes, libs could be solve with 
 simple 3 click in eclipse so please be patient with me :).
 I'm using Mono-D under Ubuntu 14.04 to create my project it 
 would be a library for further development process, but I'm a 
 guy who don't want to invite wheel again and again, so i wanted 
 to use Tango-D2 (for now HashMap implemenetation).
Anything wrong with the built in associative arrays that cause you not to use them?
 From what i red you cant import one static library with another 
 but somehow import o. files, or just copy sources .d to proper 
 folder and use them as yours (with proper license of course). 
 Tango-D2 by itself compiles nicely with bob and produces many 
 .o files. How to use them though ?
Forget the word 'import' for a minute. There are two basic steps to concern yourself with: compiling and linking. D's approach is the traditional C approach. We can loosely define the terms like so: compile: take source files as input and generate object files as output link: take object files as input and generate executables (or shared libraries, but let's not confuse things) as output. In order to compile, the compiler needs to be aware of every symbol that is visible and usable in the source module it is currently compiling. As an example, consider the following two files: main.d something.d When compiling main.d, all of the symbols inside main.d are visible by default. In order for main.d to use the symbols in something.d, it must 'import' something.d. import something; void main() { aFunctionInSomething(); } Assuming the implementation of aFunctionInSomething lives in something.d, it is now visible inside main.d because of the import. Take away the import, and you get a /compiler error/. The compiler doesn't know about that function, so you can't use it. Assuming both files live in the same directory, they can be compiled with this command: Once the object files are generated, they are passed to the linker. The important thing to understand here is that the 'import' statement in the source code above has absolutely no bearing on the link stage. It is exclusively for the compiler. The linker will never, ever, see it. All the linker cares about are symbols in the object files. To fully appreciate that, try this experiment. Take the main.d source as it is above. Then implement something.d like so: module something; import std.stdio; void aFunctionInSomething() { writeln("Something"); } Next, cd to the directory where you saved the files and compile them both: dmd -c main.d dmd -c something.d The -c option tells the compiler to only generate the object files and do not pass them to the linker. The result is that you will now have two object files. If you next take the following step (assuming Windows -- change .obj to .o elsehwere): dmd main.obj something.obj The compiler will recognize you've passed it object files and will hand them off to the linker. However, try this: dmd main.obj Using the default linker on Windows (OPTLINK -- passing -m32mscoff or -m64 uses the Microsoft linker if you have it installed, but the source must be compiled with the same flag) yields the following output: OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html main.obj(main) Error 42: Symbol Undefined _D9something20aFunctionInSomethingFZv main.obj(main) Error 42: Symbol Undefined _D9something12__ModuleInfoZ --- errorlevel 2 These are linker errors. You can know this because of two things: the big OPTLINK in the first line and the error type 'Symbol Undefined'. The Microsoft linker produces this: main.obj : error LNK2001: unresolved external symbol _D9something12__ModuleInfoZ main.obj : error LNK2019: unresolved external symbol _D9something20aFunctionInSomethingFZv referenced in function _Dmain main.exe : fatal error LNK1120: 2 unresolved externals You can know these are linker errors because of the Microsoft erro codes containing the 'LNK' prefix and because of 'unresolved external symbol', which is the equivalent of OPTLINK's 'Symbol Undefined'. It's important to be able to distinguish linker errors from compiler errors. When you pass both objects on the command line, the linker is then able to find the symbol it needs. A static library is one or more object files bundled into a single file: dmd lib something.d This will create a static library called something.lib. Then you can do this: dmd main.d something.lib In this particular case, it's exactly equivalent to the following: dmd -c something.d dmd main.d something.obj The benefit of static libraries is when you have multiple object files: dmd lib foo.d bar.d baz.d dmd main.d foo.lib Much more convenient to deal with one library than three object files.
 If using sources by just copping them into one folder, creating 
 Mono-D project, dmd complains about many, many errors, mostly 
 import errors (in tango.sys.win32). I fixed them adding version 
 to each of included files and adding some imports first:
 module tango.sys.win32....
 version(Windows){
 ...
 ...
 }

 But i think I'm doing something wrong, if Tango-D2 compiles 
 with bob it should also by creating project in Mono-D (or this 
 is linking problem ?). In Mono-D there is also possibility in 
 Project-> Options-> Build-> Compiling to add Libraries (there 
 is a tick Link static libraries from nested dependencies) how 
 to use this ? Or rather how should i obtain what i want ?
To use a library, you need two things, the source files (or D interface files, which contain all of the type and function names, but with most of the code stripped out) and the library file. If the library file does not exist, you have to compile it first. Most libraries ship with a build script of some sort -- a makefile, a DUB configuration, and so on. I haven't used Tango since the D1 days, but I see that Tango-D2 has a dub.json. So you should be able to do this: Assume 'tangoroot' refers to the directory into which you've pulled the tango source from github. cd tangoroot dub -brelease This will build a release version of the library. Next, you'll need to tell the compiler where to find both the source files (for resolving imports during the compilation stage) and the library (so that it can tell the linker where to find the static library). Looking at the Tango-D2 setup, I see the source files are all intended to be imported directly from the root directory and dub.json is configured to output the library in the same directory. You can tell the compiler where the source files are on the command line with the -I switch. How you tell it where the library files are is a different story. It depends entirely on the linker you're using. On Windows, it's easier just to feed the compiler the full library path. Assuming tangoroot is C:\dev\tango: dmd -IC:\dev\tango main.d C:\dev\tango\tango.lib That should do it. On other systems, you would have to do it like this (for simplicity, let's assume tango is in ../libs/tango, relative to the project directory): dmd -I../libs/tango -L-L../libs/tango main.d -L-ltango Here, in -L-L, the first -L tells dmd the next flag is a linker flag and should be passed to the linker. The second -L is the linker flag telling the system linker a directory in which to look for libraries. In -L-l, the -L again tells dmd the next flag is a linker flag. The -l (lowercase L) tells the linker the name of a library to link with. IIRC, you may be able to do the following, too: dmd -I../libs/tango main.d -L-l../libs/tango/libtango.a When using an IDE like Mono-D, all of this must be configured in the project settings. You've already discovered where to tell it which libraries to link with. I've never used Mono-D, so I don't know if it allows you to specify the full path to a library or if it requires you to also configure a library directory separately. At any rate, you need to configure it to know which libraries to link with, where to find them, and where to find the imported files.
Mar 12 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Sunday, 13 March 2016 at 01:06:33 UTC, Mike Parker wrote:

 it. Assuming both files live in the same directory, they can be 
 compiled with this command:
Somehow I deleted that line: dmd main.d something.d
Mar 12 2016
next sibling parent Voitech <woipoi gmail.com> writes:
On Sunday, 13 March 2016 at 01:08:29 UTC, Mike Parker wrote:
 On Sunday, 13 March 2016 at 01:06:33 UTC, Mike Parker wrote:

 it. Assuming both files live in the same directory, they can 
 be compiled with this command:
Somehow I deleted that line: dmd main.d something.d
Wow. Thank You very much for so wide description! I will try it and see if have any more questions. Cheers
Mar 14 2016
prev sibling parent reply Zardoz <luis.panadero gmail.com> writes:
On Sunday, 13 March 2016 at 01:08:29 UTC, Mike Parker wrote:
 On Sunday, 13 March 2016 at 01:06:33 UTC, Mike Parker wrote:

 it. Assuming both files live in the same directory, they can 
 be compiled with this command:
Somehow I deleted that line: dmd main.d something.d
Not would be more easy to simply add a dependency to tango on dub.SDL ? I ask...
Mar 14 2016
parent reply Jaocb Carlborg <doob me.com> writes:
On Tuesday, 15 March 2016 at 06:54:45 UTC, Zardoz wrote:

 Not would be more easy to simply add a dependency to tango on 
 dub.SDL ? I ask...
Yes. Mike gave a very long explanation that can be summed up by saying: add Tango as a dependency to your dub.json/sdl. -- /Jacob Carlborg
Mar 15 2016
parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 15 March 2016 at 08:40:31 UTC, Jaocb Carlborg wrote:
 On Tuesday, 15 March 2016 at 06:54:45 UTC, Zardoz wrote:

 Not would be more easy to simply add a dependency to tango on 
 dub.SDL ? I ask...
Yes. Mike gave a very long explanation that can be summed up by saying: add Tango as a dependency to your dub.json/sdl. -- /Jacob Carlborg
The OP said nothing about DUB and demonstrated a lack of understanding of the difference between importing and linking, a very important concept to understand.
Mar 15 2016