= FreeBSD Ports: Passing Optional Arguments to make = FreeBSD has a very neat 'ports' system, which lets you install software easily. If the ports tree is installed, all you have to do is: cd /usr/ports/ftp/proftpd make make install make clean That will download the software you've chosen (''proftpd'' in this case), configure it, make it, install it, and then cleanup. You can even shorten it to one command if you want to be brave: make install clean == Non-Default Options == What if you don't want the default options for your particular install? There are a number of ways to customize your install: === make config === If you type ''make config'', //and the port supports it// (not all ports do), you'll get a menu with the various options you can use for that port. For example, for ''proftpd'', you'll see a bunch of options such as ''MYSQL'' (enable MySQL support), ''QUOTA'' (enable quota management), and ''IPV6'' (enable IPv6 support). Check the ones you want, uncheck the ones you don't, and you're off to the races. To see the current config, type ''make showconfig'', and reset the config to the default, type ''make rmconfig''. === Using make's -D command line argument === If you look at the ''makefile'' for a given port, you'll see most of the options are included if some variable (such as ''WITH_RADIUS'' or ''WITH_IPV6'') is defined. For example, here is a snippet from the ''proftpd'' ports ''makefile'': .if defined(WITH_RADIUS) MODULES:=${MODULES}:mod_radius .endif The ''-D'' command line switch lets you define a variable to be ''1'' (thus making it defined). If you do: make -DWITH_RADIUS you'll trigger the ''if'' statement in the ''makefile'', and thus proftpd will get compiled with Radius support. You can use multiple -D options, e.g. make -DWITH_RADIUS -DWITH_IPV6 -DWITH_BAN To figure out what options are available, look at the documentation (or just look at the ''makefile''!) === Setting a variable manually: VARIABLE=VALUE === ''make'' also lets you set variables manually via the command line, which is useful if you need to set a variable to a specific value: make WITH_RADIUS=1 LOCALBASE=/usr/local Setting ''WITH_RADIUS=1'' does almost, but not quite, the same thing as ''-DWITH_RADIUS''. To understand the difference, you need to understand ''make'''s idea of 'variable context'. Basically, a variable can exist in any of four different levels (or 'contexts'); if the same variable is defined in two contents, the one with the higher (bigger) number on the following list will override the one with the lower number. The contexts are: 1. Environment variables: Variables defined as part of make's environment. 2. Global variables: Variables defined in the makefile or in included makefiles. 3. Command line variables: Variables defined as part of the command line. 4. Local variables: Variables that are defined specific to a certain target. If you look at the man page for ''make'', you'll see it says: -D variable Define variable to be 1, in the global context. variable=value Set the value of the variable variable to value. That part about //in the global context// is key. If you set a variable with ''-D'', the ''makefile'' can change or overwrite it, because **it is in the same context as variables defined in the ''makefile''** (#2 on the above list). But, if you define it to the exact same value with ''VARIABLE=1'', the ''makefile'' **cannot** change it, because it has been defined in the 'command line context' (#3), and is thus higher than #2. This is a subtle difference, but has caused no end of frustration in the past, so keep it in mind. == Setting a variable in the environment == ''-D'' can only set a variable to a value of ''1''. So how do you set a variable to a specific value (e.g. ''/usr/local'') in the global context (and thus let the ''makefile'' change it)? I'm not aware of a way to set a variable in the global context without altering the ''makefile'', but you can set an environment variable, which is a lower context, and then let ''make'' read it. So you might do: LOCALBASE=/usr/local export LOCALBASE make make install LOCALBASE= This isn't ideal, but certainly works. Comments welcome.