Environment variables in Makefile - makefile

I'm looking through a Makefile for a java project, and can't find any definition for the variable CLASSPATH:
JFLAGS = -g -Xlint:unchecked -Xlint:deprecation \
-sourcepath .. -classpath ..:$(CLASSPATH)
CLASSES = $(SRCS:.java=.class)
...
...
Does this refer to an environment variable ('echo $CLASSPATH' in bash)?
I don't see any references to another Makefile in another directory (e.g. maybe including definitions from a global Makefile?)

Makefiles can indeed reference environment variables, which is exactly what CLASSPATH is in this context. Per Wikipedia,
Classpath is a parameter in the Java Virtual Machine or the Java
compiler that specifies the location of user-defined classes and
packages. The parameter may be set either on the command-line, or through an environment variable.
On Linux, you are correct in that you can view the variable with echo $CLASSPATH. To set the variable, you can use export CLASSPATH=/path/to/classfiles

Related

Bazel environment variables in build rules

I want to refer to a DirectX SDK in the BUILD file. The problem is that (as far as I understand) Bazel supports passing environment variables only through --action_env=DXSDK_DIR argument for Bazel and it is meant to be used in actions, which must be defined in a plugin (.bzl file).
Is there any easier way to refer to the environment variable by using it as Make variable (includes = [ "$(DXSDK_DIR)/Include" ]) or do I need to write a plugin?
In principle you need a cc_library rule whose hdrs attribute globs the DirectX headers. For that you need to pretend that the DX SDK is part of your source tree. Bazel offers "repository rules" for that purpose.
1. Create a repository rule for the DirectX SDK
Depending on whether the SDK's location is known or needs to be discovered, you have two options.
a. Fixed SDK location
You can use this approach if you don't need to read any environment variables, run any binaries, or query the registry to find where the SDK is. This is the case if everyone who builds your rules will install the SDK to the same location.
Just add a new_local_repository rule to your WORKSPACE file, point the rule's path at the SDK's directory and write a simple build_file_content for it.
Example:
new_local_repository(
name = "directx_sdk",
path = "c:/program files/directx/sdk/includes",
build_file_contents = """
cc_library(
name = "sdk",
hdrs = glob(["**/*.h"]),
visibility = ["//visibility:public"],
)
""")
This rule creates the #directx_sdk repository with one rule in its root package, #directx_sdk//:sdk.
b. SDK discovery
You need to follow this approach if you need to read environment variables, run binaries, or query the registry to find where the SDK is.
Instead of using a new_local_repository rule, you need to implement your own. More info and examples are here.
Key points:
if your repository rule needs to read environment variables, add them to the list repository_rule(environ), e.g. repository_rule(..., environ = ["DXSDK_DIR"])
if you need to run some binaries that tell you where the SDK is, use repository_ctx.execute. You can use repository_ctx.which to find binaries on the PATH.
if you need to do registry queries, use repository_ctx.execute with reg.exe /query <args>
2. Depend on the SDK's cc_library
In your project, just depend on the SDK's library as if it was an ordinary cc_library:
cc_library(
name = "render",
...
deps = [
...
"#directx_sdk//:sdk",
],
)

Necessity of include_directories command in cmake project

I'm following a tutorial on CMake and I have problems understanding the necessity of using the 'include_directories' command at one point.
Let me explain the project first:
In my working directory I have:
- a main.cpp function, a CMakeLists.txt(the main one), a configuration file, a 'MathFunction' directory and a 'build' directory
In the MathFunction directory I have:
- a CMakeLists.txt file that will be invoked by the main one
- A file 'mysqrt.cxx' that contains the implementation of a function which will be used in 'main.cpp' application
- A 'MathFunctions.h' header file that contains the prototype of that function
In the CMakeLists from 'MathFunction' directory I'm creating a library using code from 'mysqrt.cxx' like this:
add_library(MathFunctions mysqrt.cxx)
This snippet is a part of my main CMake code:
# add the MathFunctions library?
#
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions") # WHY DO WE NEED THIS
add_subdirectory (MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
add_executable(Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)
Now I do not understand why I need too add that 'include_directories' command in order to use the library? Shouldn't it be enough that the last command 'target_link_libraries' links the already created executable and libraries togheter so there would be no need to also include_directories?
Thank you for reading and I'm sorry if I have not explained it very well but I hope you will understand what I mean :D
Command include_directories sets directories for header files (.h) to be searched. Linking (target_link_libraries) with a library basically specifies only a library file (.so, .dll or other type). As you see, these are different things.
When linking executable with a library target, CMake propagates (more precisely, "consumes") some properties of that library target to the executable. Among these properties there is INTERFACE_INCLUDE_DIRECTORIES property, which adds include directories to the executable.
So, when a library target has INTERFACE_INCLUDE_DIRECTORIES property correctly being set, you don't need to explicitly specify include directories for executable:
MathFunctions/CMakeLists.txt:
add_library(MathFunctions mysqrt.cxx)
# Among other things, this call sets INTERFACE_INCLUDE_DIRECTORIES property.
target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
CMakeLsits.txt:
add_executable(Tutorial tutorial.cxx)
# This also propagates include directories from the library to executable
target_link_libraries (Tutorial MathFunctions)
Note, that using simple
# This *doesn't* set INTERFACE_INCLUDE_DIRECTORIES property.
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
in MathFunctions/CMakeLists.txt doesn't imply propagating include directories to the linked executable.

What is the exact role of the DEPENDS in Makefile?

Here is a sample of my Makefile.
define Package/luci-app-myapp
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=GUI for myapp package
PKGARCH:=all
DEPENDS:=+myapp
endef
What is the exact role of the DEPENDS in this Makefile?
And what elements can be the value of the DEPENDS?
DEPENDS is basically a variable. In openwrt this variable is used to define dependency between the packages.
Detailed use of this variable is documented in openwrt link

CMake Hierarchical Project Management Without Abusing Libraries

I have a project where there's only a handful of logical groupings for generating static libraries. However for convenience I want to have the library's source code to be managed with more granular folders.
Currently the only way I know to do this in CMake without having a library for each folder is to just list files as you would normally in with their relative paths:
add_library(SystemAbstraction STATIC "Some/Path/File.cpp")
However I can see this getting unwieldy as the project grows in size with all the different paths.
I tried to see if I could have a CMakeLists.txt in each folder and just use a variable in the base CMakeLists.txt when adding library dependencies. But it seems that add_subdirectory doesn't also import variables?
For expanding the scope of a variable inside a subdirectory, use the PARENT_SCOPE option of set. For example, you can test that if you have
# CMakeLists.txt
set(SRCS main.c)
add_subdirectory(foo)
message(${SRCS})
in the root directory and
# foo/CMakeLists.txt
set(SRCS ${SRCS} foo.c PARENT_SCOPE)
in a subdirectory then it will print main.c foo.c, i.e., the variable is correctly imported into the base CMakeLists.txt.
An option would be to use the object library feature of CMake. You still can but doesn't need to organise your CMake script into subdirectories:
add_library(lib1 OBJECT <srcs>)
add_library(lib2 OBJECT <srcs>)
...
add_library(mainlib $<TARGET_OBJECTS:lib1> $<TARGET_OBJECTS:lib2>)
You can set different compile flags for each object library:
target_include_directories(lib1 PRIVATE incl-dir-for-lib1)
target_compile_definitions(lib2 PRIVATE def-for-lib2)
You still need to set link libraries on your main library:
target_link_libraries(mainlib PRIVATE deps-of-lib1 deps-of-lib2)
Related documentation: Object Libraries

Makefile, main function, ClassNotFound

I have a Java program, and write a makefile to compile it on Linux.
My project organized like this (Run.java is the main entry)
Program -
Src -
(package)adb.Bing_WebResults
Run.java
(package)adb.jsonModel
*.java
(package)adb.models
*.java
bin -
lib -
gson.jar
commons.jar
resource -
*.txt
This is my makefile:
# My project require 3 parameters from user input.
default: Run.class
Run.class: src/adb/Bing_WebResults/Run.java
javac -sourcepath src/ -classpath lib/*.jar -d bin/ src/adb/Bing_WebResults/*.java src/adb/jsonModels/*.java src/adb/models/*.java
run:
java -classpath bin/:lib/*.jar Run "$(ARG1)" "$(ARG2)" "$(ARG3)"
When I use "make run" command in Linux terminate, exception shows that "Could not find the main class: Run"
Are there something wrong with my makefile? Wrong path or something?
There are many things that could potentially be wrong, but the most apparent issues are the incorrect dependencies of the targets in your makefile.
First of all, the target run should have a dependency on Run.class. If you do make run then make looks at the target called run. In your makefile, this target does not have any dependencies defined, and it will execute the line java ... without checking whether the actual compiled class Run.class exists. As a consequence, if you do make run from a clean situation, your source code will not be compiled and the java command will fail because the compiled class is missing.
Your dependency of default on Run.class is incorrect as well, because Run.class will exist in the bin directory, not in the working directory. The line below mentions the target Run.class as well.
There are several ways to improve your makefile. See below an example of corrected code with some variables added to avoid repeated expressions. This approach is a matter of style and preference though.
BINDIR := bin
RUNCLASS := Run
RUNBINARY := $(BINDIR)/$(RUNCLASS).class
SRCDIR := src/adb/Bing_WebResults
RUNSRC := $(SRCDIR)/$(RUNCLASS).java
# Note: the default target below is superfluous at this moment
default: $(RUNBINARY)
$(RUNBINARY): $(RUNSRC)
javac -sourcepath src/ -classpath lib/*.jar -d $(BINDIR) $(SRCDIR)/*.java src/adb/jsonModels/*.java src/adb/models/*.java
run: $(RUNBINARY)
java -classpath $(BINDIR):lib/*.jar $(RUNCLASS) "$(ARG1)" "$(ARG2)" "$(ARG3)"
This works for me in a simplified, comparable setup -- it might work for you as well. Looking at the snippet you provided, there are most likely other dependencies or changes that need to be added to complete your makefile correctly. Potentially, you might have to add package information to your run command and dependency expressions, but that depends on your source code. Your post does not contain enough information to provide a complete solution.
P.S.: Do not forget to replace spaces by tabs if you copy this code to your own makefile.
At last you need to specify the package when running since you dont seem to have the main class in default package.
java -classpath bin com.example.Run arg1 arg2 ...
It turns out that two points should be noticed:
(1) Run is in a package, so it should be "adb.Bing_WebResults.Run.class" in makefile.
(2) external jar files should be concatenated by : (e.g. lib/a.jar: lib/b.jar)

Resources