I'm trying to build the examples at https://github.com/mirage/mirage-tcpip in the folder "examples".
First I did opam install . in the root directory to install all dependencies. Then I did dune build and it build everything in _build, lots of .a, .cma, .cmx, .cmi, .cmxa files that I don't know what are for (can somebody explain?).
Anyways, I think the examples have to be built separately, because they have their own dune files. But I tried running dune build on them and got:
root#66f08fd7c55b:/workspaces/ocaml_env/mirage-tcpip/examples/ping# dune build
Entering directory '/workspaces/ocaml_env/mirage-tcpip'
root#66f08fd7c55b:/workspaces/ocaml_env/mirage-tcpip/examples/ping# ls
dune ping.ml
root#66f08fd7c55b:/workspaces/ocaml_env/mirage-tcpip/examples/ping# cat dune
(executables
(names ping)
(libraries cmdliner logs logs.fmt tcpip.icmpv4-socket))
root#66f08fd7c55b:/workspaces/ocaml_env/mirage-tcpip/examples/ping# dune build ping
Entering directory '/workspaces/ocaml_env/mirage-tcpip'
Error: Don't know how to build ping
Explanation of OCaml file types:
Regarding the file types in the _build directory (reference 1, reference 2):
.a are standard archive files (also known as static libraries) containing native code:
Arguments ending in .o or .a (.obj or .lib under Windows) are assumed to be C object files and libraries. They are passed to the C linker when linking in -custom mode (see the description of -custom below).
.cma are the OCaml byte code equivalent of .a files, so static libraries, but with platform-independent OCaml byte code instead of machine-dependent native code:
Arguments ending in .cma are taken to be libraries of object bytecode. A library of object bytecode packs in a single file a set of object bytecode files (.cmo files).
.cmx contain meta-data for how to link native code object files together:
Arguments ending in .ml are taken to be source files for compilation unit implementations. ... From the file x.ml, the ocamlopt compiler produces two files: x.o, containing native object code, and x.cmx, containing extra information for linking and optimization of the clients of the unit.
.cmi are compiled interface definition files:
Arguments ending in .mli are taken to be source files for compilation unit interfaces. Interfaces specify the names exported by compilation units: they declare value names with their types, define public data types, declare abstract data types, and so on. From the file x.mli, the ocamlopt compiler produces a compiled interface in the file x.cmi.
.cmxa are native code library files that combine .a/.o and and .cmx files, so like .a but with additional linking information from the .cmx files:
Arguments ending in .cmxa are taken to be libraries of object code.
Building the example
Regarding the build of the ping example, to build an executable target with dune, you have to append .exe to the target name (reference):
Note that native code executables will have the .exe extension on all platforms (including non-Windows systems).
So the full sequence of build commands would be:
Install dependencies:
$ opam install .
Build mirage-tcpip:
$ dune build
Build the ping example:
$ cd example/ping
$ dune build ping.exe
Run the binary:
# dune exec ./ping.exe 8.8.8.8
Alternatively, from the mirage-tcpip directory:
# ./_build/default/examples/ping/ping.exe 8.8.8.8
Related
To learn the processes behind compilation of Ada programs (without resorting to using gpr), I've decided to compile one of my projects manually. To compile a program, I run the following command on each .adb file therein (not manually, however):
$ gcc -c src/<file>.adb -o obj/<file>.o
That compiles all the files and puts them in the obj directory.
Or rather, it would. There is a slight problem with this. I have an archive (static library) that I've generated from another project, called libapples.a, containing package Apples. The Apples package is used by the files you see me compiling above.
Since libapples.a doesn't have source files anymore (given its archive format), it's not viable (not even possible) to provide the sources of that library to the command above using -I switches; on the other hand, if I don't have the sources included, the command above comes back to me saying:
<file>.adb:<y>:<x>: file "apples.ads" not found
gnatmake: "src/<file>.adb" compilation error
I've attempted to include the library in the compilation process by using flags -L and l (which I believe is how you'd do it in C; feel free to correct me if I'm wrong). In another attempt I placed the archive right in the source directory.
How does one go about including a library in the compilation process?
apples.ads is somewhat like a header in C and you definitely need it for your file to compile. You should use -I to point gcc to the directory where apples.ads is located in.
Be aware that compiling an Ada source not only yields an object file, but also an Ada Library Information (.ali) file. You'll need that for the next step. You should not use the -o flag because it may lead to your .o and .ali files having different names.
On the other hand, since you only want to produce an object file, you should use -c to tell gcc to only compile. In other languages like C, gcc compiles and links by default; in Ada, the process is more complex.
After compilation, you need to call gnatbind on the .ali file of your main program. This generates a package that will take care of proper initialization of everything. To do that, gnatbind needs the .ali file of the Apples package! You can specify the .ali search directory with -aO.
Finally, gnatlink called on the main .ali file will link everything together. It figures out itself which object files and libraries it needs. It will append the necessary options to the linker, including the reference to libapples.a. It also compiles the package generated by gnatlink.
I don't know exactly what gnatlink will do under the hood; you could probably compile the package generated by gnatbind manually and then call the linker if you can figure out the proper arguments.
I am trying to create a simple CMake that retrieves the DLLs of Qt and copy it in the directory in which cmake creates my executable.
It works great using g++ or clang, but MSVC (Visual Studio 2017) creates a Debug or Release directory.
I can't find a way to retrieve the path to the real directory in which the executable is written (${CMAKE_CURRENT_BINARY_DIR} returns the directory parent of Release or Debug).
I've seen people using the target property RUNTIME_OUTPUT_DIRECTORY but it is empty when I use it.
Any idea how I can do this ? I do not want to change the output directory, I just want to know its path (so I do not want to change the value of RUNTIME_OUTPUT_DIRECTORY)
Thanks!
In Visual Studio, during configuration step (when CMakeLists.txt files are processed) build type is not set, so no build-type-dependent variable or property is usable directly. Instead, generator-expressions should be used.
E.g., output directory for executable or library target can be extracted with $<TARGET_FILE_DIR:tgt> generator expression. It will return full directory, with "Release/" or "Debug/" already appended.
Note, that generator expressions can be used only when their usage is explicitly allowed in documentation. E.g., they cannot be used in message() command.
Alternatively, you may explicitely set variable CMAKE_RUNTIME_OUTPUT_DIRECTORY, so for every build type will just append appropriate subdirectory to it. But for extracting this subdirectory, you should again resort to generator expressions: $<CONFIG>.
Technically, it is possible to set the same output directory for any build type. But this is not recommended, because a file from one build type will be overwritten by the file from another build type.
Example for Visual Studio 2022 and CMake.
Place this at the end of CMakeLists.txt:
if (WIN32)
add_custom_command(
TARGET qcpp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/include/external/c.dll" "${CMAKE_BINARY_DIR}"
COMMAND_EXPAND_LISTS
)
endif()
See list of CMake variables.
Note the "qcpp" in the preceding command. This is the project name and should match this line at the start:
project ("qcpp")
Appendix A - Testing
To verify, if you generate a Visual Studio Project using mkdir x && cd x && cmake .., you can see that CMake has added a post-build step to the solution config:
As of CMake 3.21+, the $<TARGET_RUNTIME_DLLS:tgt> generator expression can help copy dependent DLLs to the build tree. Quoting the documentation:
List of DLLs that the target depends on at runtime. This is determined by the locations of all the SHARED and MODULE targets in the target's transitive dependencies. Using this generator expression on targets other than executables, SHARED libraries, and MODULE libraries is an error. On non-DLL platforms, it evaluates to an empty string.
This generator expression can be used to copy all of the DLLs that a target depends on into its output directory in a POST_BUILD custom command.
Docs link: https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_RUNTIME_DLLS
An example of how to use this (adapted from the docs) follows:
find_package(foo REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE foo::foo)
if (WIN32)
add_custom_command(
TARGET main POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_RUNTIME_DLLS:main> $<TARGET_FILE_DIR:main>
COMMAND_EXPAND_LISTS
)
endif ()
The if (WIN32) check ensures that $<TARGET_RUNTIME_DLLS:main> won't be empty, which would cause the command to fail (rather than do nothing). COMMAND_EXPAND_LISTS makes sure that the semicolon-delimited list returned by $<TARGET_RUNTIME_DLLS:main> will be split into multiple arguments, rather than passed as a single argument with (escaped) semicolons in it.
Note also that UNKNOWN libraries will be ignored by this generator expression. These are common when using the built-in Find modules, rather than using a library's first-party CMake config-mode package. In these cases, you will have to manually inspect the module variables to find the library paths and add custom commands for each one yourself.
For Qt specifically, I would expect the newer CMake integration in Qt6 to "just work", though I haven't tested it. It might also work in Qt5, but again I haven't tested it.
I have a project with some folders which happen to contain source files with the same names.
My source tree looks like this:
project.pro
foo/
conflict.h
conflict.cpp
bar/
conflict.h
conflict.cpp
some.h
other.h
files.h
main.cpp
Per default, qmake generates a Makefile which will produce a build tree like this:
conflict.o
main.o
target
Where conflict.o is the object file resulting for both foo/conflict.cpp and foo/conflict.h.
I can't to change their names because they are generated using an external tool and forcing different file names would imply to change their contents, so this is not an option.
I also don't want to use qmake SUBDIRS template because this would imply that (1) every subdir is built separately as a library and thus very much complicate the overall build process (in my eyes at least) and (2) in the top level directory I can't have any source files. Or am I wrong?
Can't I just tell qmake to write the object files into separate directories within the build directory? So my build tree will look like this:
foo/
conflict.o
bar/
conflict.o
main.o
target
Or are there any other solutions neither requiring to rename the source files nor introducing something complicated like static libraries? I just can't believe that Qt didn't solve this (in my eyes simple) problem for years. (I already hat this problem 4 years ago but could rename the files in that project, while here I can't.)
If it's important: I use Qt 4.8 on both Ubuntu with G++ and Windows with mingw32.
Are you tied to qmake? If not, an alternative could be to use cmake. I just verified your usecase with a simple CMakeLists.txt like
cmake_minimum_required (VERSION 2.6)
project (conflict)
add_executable(conflict foo/conflict.cpp bar/conflict.cpp main.cpp)
which even included a source file in the top level directory (main.cpp). This properly builds the executable - the object files are created in sub directories like
./CMakeFiles/conflict.dir/main.cpp.o
./CMakeFiles/conflict.dir/bar/conflict.cpp.o
./CMakeFiles/conflict.dir/foo/conflict.cpp.o
cmake also includes support for Qt4, to automatically pull in the required include paths and libraries. It might require some effort to migrate from qmake to cmake, but given the requirements you have I would give it a try.
I want to copy a data file from a directory in my source tree to the directory of the linked app so it's available at runtime, on Windows only. There appear to be two suggested techniques: use a post target dependency to issue a DOS copy command (Including resource files in Qt Creator build directory) or use an install step (Copy a file to the build directory after compiling project with Qt), but I cannot make either work in the way I would like.
The former requires me to use qmake path variables to generate my source and destination paths, but they contain backslash path separators, which the DOS copy command cannot handle.
The install solution forces other users of my project to set up a post build step in Qt Creator before it will work (one per configuration, in fact) and I would like to avoid this, as I want to make my project work with a default Qt Creator installation.
Is there any way to do this apparently simple task that can be wholly defined in the .pro file for the project? For example, is there a way to expand qmake path variables in a platform specific way?
Though these commands run ONLY after the executable is ACTUALLY linked, this solution doesn't require an external batch file. Note: this a Windows-only solution:
From our .pri file:
win32 {
...
# Copy the appropriate dll files into the target destination directory.
QMAKE_TBB_LIBDIR = $$quote($$PWD/MySource/MyLibs/$${PLATFORM_NAME}/vc9)
QMAKE_POST_LINK = copy /y $${replace(QMAKE_TBB_LIBDIR, /, \\)}\\*.dll > $${replace($$quote(DESTDIR), /, \\)}
...
}
This places a command in the Makefile that copies all the .dll files in MyLibs/x64 or MyLibs/Win32 into the destination directory.
However, if the executable did not need to be linked, then the .dlls are NOT copied.
The post build batch file would not have this limitation.
I created simple Java Servlet: WelcomeServlet.java.
Than, I tried compile this file via:
javac WelcomeServlet.java
In result I see compile error:
package javax.servlet doesn't exit
I try find solution for this error with Google. And I find first part of answer: java compiler doesnt see servlet-api.jar file.
I know, that Apache Tomcat in it lib folder contains servlet-api.jar file.
So, I have this file, but where I must copy this file??
I try different folders:
echo %JAVA_HOME%
C:\Program Files\Java\jdk1.6.0_26
%PATH% contains this line: C:\Program Files\Java\jdk1.6.0_26\bin
So, I copy in:
%JAVA_HOME%\bin
%JAVA_HOME%\lib
%JAVA_HOME%\jre\lib
And in result same error.
And only after I copy servlet-api.jar in directory:
%JAVA_HOME%\jre\lib\ext
compilation complite sucessful.
My question: Why? Why I must copy in folder %JAVA_HOME%\jre\lib\ext ??
Where This moment describe in documentation?
And other question we have some official docs or specifications that describe folder structure for jdk folder??
You'll need to specify the directory or directories you want the compiler to search by using the -classpath command line option when running javac. The reason the compiler found your .jar in %JAVA_HOME%\jre\lib\ext is because it searches the extension directories by default.
This is for Java 1.5, but I believe it is more or less still correct:
http://docs.oracle.com/javase/1.5.0/docs/tooldocs/findingclasses.html
The link Shaun provides is a more complete answer. But in short, using the classpath is the best way to introduce 3rd party or external (to the JDK/JRE) libraries. The classpath is a concept much like the %PATH% or the $PATH variables, but specifies locations for java to use for lookup rather than the shell to use for lookup of executables.
The classpath provides the java compiler or java virtual machine a list of items to use when searching for resources. This "path" may include directories or files. It will typically include jar files and sometimes locations of configuration files. Many Java based lookup schemes for files configuration or otherwise use some variant of what is accomplished by [Class#getResourceAsStream()][1]'s use of walking the Classpath.
I have rarely seen an incident where putting a jar file in the lib/ext location was preferred to utilizing the Classpath.
The classpath is typically an environment variable (%CLASSPATH% or $CLASSPATH) or specified on the command line when running java or javac (e.g. -cp or -classpath see the help from the executable you are running).
Build tools such as Ant and Maven will also provide abstractions to defining the list of jars to be utilized by your applications and are highly recommended to be used for any length of repetitive change code, build, test, run cycles.