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.

Reply via email to